package com.mzkj.wanjulaile.mobile.api.modules.session.service;

import com.mzkj.common.data.StatusCode;
import com.mzkj.common.utils.AccessTokenUtils;
import com.mzkj.common.utils.DateUtils;
import com.mzkj.common.utils.StringUtils;
import com.mzkj.wanjulaile.mobile.api.common.entity.ResultEntity;
import com.mzkj.wanjulaile.mobile.api.common.service.BaseService;
import com.mzkj.wanjulaile.mobile.api.common.service.ServiceException;
import com.mzkj.wanjulaile.mobile.api.modules.session.entity.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.SystemEnvironmentPropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mzkj.wanjulaile.mobile.api.modules.session.mapper.SessionMapper;

import javax.validation.Valid;
import java.util.Date;

/**
 * SessionService实现类
 * Created by wangxw on 2016/12/13.
 */
@Service("sessionService")
public class SessionServiceImpl extends BaseService implements SessionService {

    @Autowired
    private SessionMapper sessionMapper;
    @Value("${access_token_expires:432000}")
    private long accessTokenExpires;
    @Value("${refresh_token_expires:2592000}")
    private long refreshTokenExpires;

    @Override
    @Transactional
    public Session insert(Session session) {
        if (session == null || session.getAccountId() == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(session.getAccountId())
                .append(System.currentTimeMillis())
                .append(session.getClientType());
        session.setAccessToken(AccessTokenUtils.createToken(sb.toString()));
        sb.append("refresh_token");
        session.setRefreshToken(AccessTokenUtils.createToken(sb.toString()));
        Date nowDate = new Date();
        session.setCreateDate(nowDate);
        session.setUpdateDate(nowDate);
        sessionMapper.insert(session);
        return session;
    }

    @Override
    @Transactional
    public Session findByAccessToken(String accessToken) {
        Session session = null;
        ResultEntity<String> resultEntity = validAccessToken(accessToken);
        if (StatusCode.SC0.getValue().equals(resultEntity.getStatusCode())) {
            session = sessionMapper.findByAccessToken(accessToken);
        }
        return session;
    }

    @Override
    //没有校验accessToken值，其他地方不要引用
    public Session findByAccessToken2(String accessToken) {
        return sessionMapper.findByAccessToken(accessToken);
    }

    @Override
    public Session findByRefreshToken(String refreshToken) {
        return null;
    }

    @Override
    @Transactional
    public Session updateByAccessToken(Session session) {
        return null;
    }

    @Override
    @Transactional
    public Session updateByRefreshToken(Session session) {
        return null;
    }

    @Override
    @Transactional
    public void delete(Long id) {
        sessionMapper.delete(id);
    }

    @Override
    public int delete(String accountId) {
        return sessionMapper.deleteByAccount(accountId);
    }

    @Override
    @Transactional
    public ResultEntity<String> validAccessToken(String accessToken) {
        if (StringUtils.isEmpty(accessToken)) {
            return new ResultEntity<>(StatusCode.SC4001);
        }
        Session session = sessionMapper.findByAccessToken(accessToken);
        if (session == null) {
            return new ResultEntity<>(StatusCode.SC2000);
        }
        ResultEntity<String> resultEntity;
        long curMilliscond = System.currentTimeMillis();
        if ((curMilliscond - DateUtils.getMilliscond(session.getUpdateDate())) / 1000 > session.getExpiresIn()) {
            resultEntity = new ResultEntity<>(StatusCode.SC2001);
        } else {
            session.setUpdateDate(new Date());
            sessionMapper.updateByAccessToken(session);
            resultEntity = new ResultEntity<>(StatusCode.SC0);
        }
        return resultEntity;
    }

    @Override
    @Transactional
    public ResultEntity<Session> validateToken(String accessToken, String refreshToken) {
        if (StringUtils.isEmpty(accessToken)) {
            return new ResultEntity<>(StatusCode.SC4001);
        }
        Session session = sessionMapper.findByAccessToken(accessToken);
        if (session == null) {
            return new ResultEntity<>(StatusCode.SC2000);
        }
        ResultEntity<Session> resultEntity;
        long curMilliscond = System.currentTimeMillis();
        if ((curMilliscond - DateUtils.getMilliscond(session.getUpdateDate())) / 1000 > session.getExpiresIn()) {
            resultEntity = refreshToken(refreshToken);
        } else {
            resultEntity = new ResultEntity<>(StatusCode.SC0, session);
        }
        return resultEntity;
    }

    @Override
    @Transactional
    public ResultEntity<Session> refreshToken(String refreshToken) {
        if (StringUtils.isEmpty(refreshToken)) {
            return new ResultEntity<>(StatusCode.SC4001);
        }
        Session session = sessionMapper.findByRefreshToken(refreshToken);
        if (session == null) {
            return new ResultEntity<>(StatusCode.SC2002);
        }
        ResultEntity<Session> resultEntity;
        long curMilliscond = System.currentTimeMillis();
        if ((curMilliscond - DateUtils.getMilliscond(session.getCreateDate())) / 1000 > refreshTokenExpires) {
            resultEntity = new ResultEntity<>(StatusCode.SC2003);
        } else {
            try {
                //如果accessToken过期更新accessToken,如果没有过期则刷新更新时间,相当于延长过期时间
                if ((curMilliscond - DateUtils.getMilliscond(session.getUpdateDate())) / 1000 > accessTokenExpires) {
                    session.setAccessToken(AccessTokenUtils.createToken(session.getAccountId(), session.getClientType()));
                }
                Date nowDate = new Date();
                session.setCreateDate(nowDate);
                session.setUpdateDate(nowDate);
                int rs = sessionMapper.updateByRefreshToken(session);
                if (rs == 1) {
                    resultEntity = new ResultEntity<>(StatusCode.SC0, session);
                } else {
                    resultEntity = new ResultEntity<>(StatusCode.SC5000);
                }
            } catch (ServiceException e) {
                resultEntity = new ResultEntity<>(StatusCode.SC5000);
                logger.error(e.getMessage(), e);
            }
        }
        return resultEntity;
    }
}
